<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<!-- Head -->

<head>
  <meta charset="utf-8" />
  <title>商品配置</title>

  <div th:replace="/system/resource/base/baseHead.template"></div>
  <link rel="stylesheet" type="text/css" th:href="${application.resourceUrl}+'/assets/js/lightbox/css/lightbox.css'" />
  <link rel="stylesheet" type="text/css" href="https://cdn.test.bestpay.net/orange/antd.1.6.5.css" />
  <!-- <link rel="stylesheet" type="text/css" href="./antd.1.6.5.css" /> -->
  <link rel="stylesheet" type="text/css" href="https://cdn.test.bestpay.net/orange/tailwindcss@2.2.19.min.css" />
  <style>
    html {
      font-size: 14px;
    }

    .page-body {
      padding: 30px;
    }

    .ant-card {
      margin-bottom: 20px;
    }

    [v-cloak] {
      visibility: hidden;
    }

    .photoOverlay {
      opacity: 0;
    }

    .photoOverlay:hover {
      opacity: 1;
    }
  </style>
</head>
<!-- /Head -->
<!-- Body -->

<body>
  <!-- 引入头部 -->
  <div th:include="/system/resource/base/baseNav.template"></div>
  <!-- /引入头部 -->
  <!-- Main Container -->
  <div class="main-container container-fluid">
    <!-- Page Container -->
    <div class="page-container">
      <!-- 引入左侧菜单 -->
      <div class="page-sidebar" id="sidebar" th:include="/system/resource/base/baseLeftMenu.template"></div>
      <!-- /引入左侧菜单 -->
      <!-- Page Content -->
      <div class="page-content">
        <!-- Page Breadcrumb -->
        <div class="page-breadcrumbs">
          <ul class="breadcrumb"></ul>
        </div>
        <!-- /Page Breadcrumb -->
        <!-- Page Body -->
        <div id="app" class="page-body" v-cloak>
          <div v-if="showTablePage">
            <a-card title="查询条件">
              <a-form-model :model="searchForm" v-bind="layout">
                <a-row :gutter="24">
                  <a-col :span="10">
                    <a-form-model-item label="商品主标题 :">
                      <a-input v-model="searchForm.commodityMainTitle" placeholder="请输入商品主标题" />
                    </a-form-model-item>
                  </a-col>
                  <a-col :span="12">
                    <a-form-model-item label="商品编码 :">
                      <a-input v-model="searchForm.spuId" placeholder="请输入商品编码" />
                    </a-form-model-item>
                  </a-col>
                </a-row>
                <a-row :gutter="24">
                  <a-col :span="10">
                    <a-form-model-item label="品牌名称 :">
                      <a-select v-model='searchForm.brandId' placeholder="请选择">
                        <a-select-option v-for="(brand, index) in brandList" :value="brand.brandId">
                          {{ brand.brandName }}
                        </a-select-option>
                      </a-select>
                    </a-form-model-item>
                  </a-col>
                  <a-col :span="12">
                    <a-form-model-item label="类目 :">
                      <a-cascader ref="searchFormCategoryCascader" :options="categorys"
                        :field-names="{ label: 'categoryName', value: 'categoryId', children: 'children' }"
                        :show-search="{ categorySearchFilter }" placeholder="输入进行搜索"
                        @change="searchFromCategoryChange" />
                    </a-form-model-item>
                  </a-col>
                </a-row>
                <a-row :gutter="24">
                  <a-col :span="10">
                    <a-form-model-item label="是否生效 :">
                      <a-select v-model='searchForm.effective' placeholder="请选择">
                        <a-select-option v-for="(effectiveStatus, effectiveIndex) in effectiveOptions"
                          :value="effectiveStatus.value">
                          {{ effectiveStatus.label }}
                        </a-select-option>
                      </a-select>
                    </a-form-model-item>
                  </a-col>
                </a-row>
                <a-row>
                  <a-col :span="24" :style="{ textAlign: 'center' }">
                    <a-button :loading="queryTableLoading" type="primary" @click="queryTableData">
                      查询
                    </a-button>
                    <a-button :style="{ marginLeft: '8px' }" @click="resetSearchFormInfo">
                      重置
                    </a-button>
                  </a-col>
                </a-row>
              </a-form-model>
            </a-card>
            <a-card title="查询结果">
              <div slot="extra">
                <a-button type="primary" @click="showDetailDialog(0)">新增</a-button>
              </div>
              <a-config-provider :locale="locales.zh_CN">
                <a-table :columns="tableColumns" :data-source="tableData" :loading="loading" :pagination="pagination"
                  row-key="id" :scroll={x:1000} bordered size="small" @change="handleTableChange">
                  <template slot="action" slot-scope="text, record, index">
                    <a-button type="primary" @click="showDetailDialog(1, record)">修改</a-button>
                    <a-button type="primary" @click="showDetailDialog(2, record)">详情</a-button>
                  </template>
                </a-table>
              </a-config-provider>
            </a-card>
          </div>
          <div v-else>
            <a-form-model :model="dialogForm">
              <a-card :title="getDialogActionTitle">
                <a-row :gutter="24">
                  <a-col :span="1"></a-col>
                  <a-col :span="10">
                    <a-form-model-item label="商品主标题 :">
                      <a-input :disabled="disableDialogFormEidt" v-model="dialogForm.commodityMainTitle"
                        placeholder="请输入商品主标题" />
                    </a-form-model-item>
                  </a-col>
                  <a-col :span="2"></a-col>
                  <a-col :span="10">
                    <a-form-model-item label="商品副标题 :">
                      <a-input :disabled="disableDialogFormEidt" v-model="dialogForm.commoditySubtitle"
                        placeholder="请输入商品副标题" />
                    </a-form-model-item>
                  </a-col>
                </a-row>
                <a-row :gutter="24">
                  <a-col :span="1"></a-col>
                  <a-col :span="10">
                    <a-form-model-item label="类目 :">
                      <a-cascader :options="categorys"
                        :field-names="{ label: 'categoryName', value: 'categoryId', children: 'children' }"
                        :show-search="{ categorySearchFilter }" placeholder="请选择类目" :disabled="disableDialogFormEidt"
                        :default-value="dialogForm.categorys" @change="dialogCategoryChange" />
                    </a-form-model-item>
                  </a-col>
                  <a-col :span="2"></a-col>
                  <a-col :span="10">
                    <a-form-model-item label="品牌名称 :">
                      <a-select v-model="dialogForm.brandId" :default-value="dialogForm.brandId" placeholder="请选择商品"
                        :disabled="disableDialogFormEidt">
                        <a-select-option v-for="(brand, index) in brandList" :value="brand.brandId">
                          {{ brand.brandName }}
                        </a-select-option>
                      </a-select>
                    </a-form-model-item>
                  </a-col>
                </a-row>
                <a-row>
                  <h3>属性信息</h3>
                </a-row>
                <a-row :gutter="24" v-for="(attributeRowItem, attributeRowIndex) in dialogForm.attributeRowList"
                  :key="attributeRowItem.attributeId || attributeRowIndex">
                  <a-col :span="1"></a-col>
                  <a-col :span="10">
                    <a-form-model-item label="属性 :">
                      <a-select label-in-value placeholder="请选择" :disabled="dialogType !== 0"
                        :default-value="{key: attributeRowItem.attributeId}"
                        @select="dialogAttributeSelect($event, attributeRowIndex)">
                        <!-- 不要换行，不然change事件回调的label值有空格和换行符 -->
                        <a-select-option v-for="attributeListItem in attributeList" :key="attributeListItem.attributeId"
                          :value="attributeListItem.attributeId"
                          :disabled="dialogForm.attributeRowList.some(item => item.attributeId === attributeListItem.attributeId)">{{attributeListItem.attributeName}}</a-select-option>
                      </a-select>
                    </a-form-model-item>
                  </a-col>
                  <a-col :span="2">
                    <a-icon v-if="dialogType === 0" @click="attrbitueRowChange(attributeRowIndex)"
                      :style="{fontSize: '30px', marginTop: '50px'}"
                      :type="attributeRowIndex === 0 ? 'plus-circle': 'minus-circle'" />
                  </a-col>
                  <a-col :span="10">
                    <a-form-model-item label="属性值 :">
                      <a-select mode="multiple" :disabled="disableDialogFormEidt" placeholder="请选择属性"
                        :ref="`attributeValueSelect${attributeRowIndex}`" option-label-prop="label"
                        :default-value="attributeRowItem.attributeValueId"
                        @select="dialogAttributeValueSelect($event, attributeRowIndex)"
                        @deselect="dialogAttributeValueDeselect($event, attributeRowIndex)">
                        <a-select-option
                          v-for="(subAttrItem, subAttrIndex) in dialogForm.attributeVlaueOptionsList[attributeRowIndex]"
                          :disabled="subAttrItem.disabled" :key="subAttrItem.attributeValueId"
                          :value="subAttrItem.attributeValueId" :label="subAttrItem.attributeValueName">
                          {{subAttrItem.attributeValueName }}</a-select-option>
                      </a-select>
                    </a-form-model-item>
                  </a-col>
                </a-row>
                <a-row :gutter="24">
                  <a-col :span="12">
                    <a-row :gutter="24" style="margin: 20px 0;">
                      <a-col :span="1"></a-col>
                      <a-col :span="22">
                        <div style="display: flex; align-items: flex-start;">
                          <div style="margin-right: 20px; line-height: 30px;">是否自动定价 :</div>
                          <a-radio-group v-model="dialogForm.autoSetPrice" @change="priceTypeChangeHandle"
                            style="display: flex; flex-direction: column;">
                            <a-radio :disabled="disableDialogFormEidt"
                              style="display: 'flex'; height: '30px'; line-height: '30px'" :value="1">
                              指定比例：供货价 *
                              <a-input type="number" :value="dialogForm.precentPrice" @change="autoPriceChangeHandle"
                                :disabled="dialogForm.autoSetPrice !== 1" style="width: 200px; margin: 0 10px;"
                                suffix="%元" />
                            </a-radio>
                            <a-radio :disabled="disableDialogFormEidt"
                              style="display: 'flex'; height: '30px'; line-height: '30px';margin-top:10px;" :value="2">
                              指定金额：供货价 +
                              <a-input type="number" :value="dialogForm.amountPrice" @change="autoPriceChangeHandle"
                                :disabled="dialogForm.autoSetPrice !== 2" style="width: 200px; margin: 0 10px;"
                                suffix="元" />
                            </a-radio>
                            <a-radio :disabled="disableDialogFormEidt"
                              style="display: 'flex'; height: '30px'; line-height: '30px';margin-top:10px;" :value="0">
                              否
                            </a-radio>
                          </a-radio-group>
                        </div>
                      </a-col>
                    </a-row>
                  </a-col>
                  <a-col :span="12">
                    <a-row :gutter="24" style="margin: 20px 0;">
                      <a-col :span="1"></a-col>
                      <a-col :span="22">
                        <div style="display: flex; align-items: flex-start;">
                          <div style="margin-right: 20px; line-height: 30px;">是否虚拟商品 :</div>
                          <a-radio-group v-model="dialogForm.virtualCommodity" @change="virtualChangeHandle"
                            style="display: flex; flex-direction: column;">
                            <a-radio :disabled="disableDialogFormEidt || dialogType!== 0"
                              style="display: 'flex'; height: '30px'; line-height: '30px';margin-top:10px;" :value="0">
                              否
                            </a-radio>
                            <a-radio :disabled="disableDialogFormEidt || dialogType!== 0"
                              style="display: 'flex'; height: '30px'; line-height: '30px'" :value="1">
                              是
                              <a-checkbox-group style="line-height: '30px';position: relative; top:5px; left: 30px;"
                                v-model="dialogForm.rechargeAccountType"
                                :disabled="dialogForm.virtualCommodity !== 1 || dialogType!== 0">
                                <a-row>
                                  <a-col :span="8">
                                    <a-checkbox value="mobile">
                                      手机号
                                    </a-checkbox>
                                  </a-col>
                                  <a-col :span="8">
                                    <a-checkbox value="QQ">
                                      QQ号
                                    </a-checkbox>
                                  </a-col>
                                  <a-col :span="8">
                                    <a-checkbox value="wechat">
                                      微信号
                                    </a-checkbox>
                                  </a-col>
                                </a-row>
                              </a-checkbox-group>
                            </a-radio>
                          </a-radio-group>
                        </div>
                      </a-col>
                    </a-row>
                  </a-col>
                </a-row>
                <a-row :gutter="24" v-if="dialogForm.tableRowList.length">
                  <a-col :span="1"></a-col>
                  <a-col :span="22">
                    <a-config-provider :locale="locales.zh_CN">
                      <a-table :columns="dialogForm.tableRowList" :data-source="dialogForm.tableDataList" key="id"
                        :scroll="{x:1000, y: 700}" bordered size="small" :pagination="false"
                        @change="handleTableChange">
                        <template slot="text" slot-scope="text, record, index">
                          <span>{{ text }}</span>
                        </template>
                        <template slot="sellingPrice" slot-scope="text, record, index">
                          <editable-cell :key="record.key" :disableEdit="disableDialogFormEidt" :text="text"
                            :input-type="'number'" @change="onCellChange(index, 'sellingPrice', $event)" />
                        </template>
                        <template slot="onHandPrice" slot-scope="text, record, index">
                          <editable-cell :key="record.key" :onhand-price-error="record.onhandPriceError"
                            :disableEdit="disableDialogFormEidt" :text="text" :input-type="'number'"
                            @change="onCellChange(index, 'onHandPrice', $event)" />
                        </template>
                        <template slot="action" slot-scope="text, record, index">
                          <a-button v-if="!record.skuId" @click="deleteDialogAttrTableRow(index, record)">删除</a-button>
                        </template>
                      </a-table>
                    </a-config-provider>
                  </a-col>
                </a-row>
                <a-row :gutter="24">
                  <a-col :span="1"></a-col>
                  <a-col :span="23">
                    <a-form-model-item label="上传商品图片 :">
                      <div class="flex">
                        <div class="relative w-24 h-24 mr-1" v-for="(photo, index) in dialogForm.mainPhotoImgList"
                          :key="index" @dragenter="dragenter($event, index, 'main')" @dragover="dragover($event, index)"
                          @dragstart="dragstart(index)" draggable="!disableDialogFormEidt">
                          <img class="w-full h-full" :src="photo.pictureUrl">
                          <div class="photoOverlay absolute top-0 left-0 flex items-center justify-center w-full h-full"
                            style="background-color: rgba(0, 0, 0, 0.5);">

                            <a-icon v-if="!disableDialogFormEidt" @click="photoDelete(index, 'main')" class="cursor-pointer"
                              :style="{fontSize: '20px', color: 'white'}" type="delete" ></a-icon>
                            <a-icon v-if="disableDialogFormEidt" @click="catPhoto(photo.pictureUrl)" class="cursor-pointer"
                              :style="{fontSize: '25px', color: 'white'}" type="zoom-in" ></a-icon>
                          </div>
                        </div>
                        <label v-if="!disableDialogFormEidt" for="mainPhotoInput"
                          class="flex border items-center justify-center flex-col w-24 h-24">
                          <a-icon type="plus" :style="{fontSize: '40px'}"></a-icon>
                        </label>
                      </div>
                      <input id="mainPhotoInput" type="file" accept="image/*" style="display: none;"
                        ref="mainPhotoInput" @change="photoInputChange('main')" />
                  </a-col>
                  </a-form-model-item>
                </a-row>
                <a-row :gutter="24">
                  <a-col :span="1"></a-col>
                  <a-col :span="23">
                    <a-form-model-item label="上传详情页图片 :">
                      <div class="flex">
                        <div class="relative w-24 h-24 mr-1" v-for="(photo, index) in dialogForm.detailPhotoImgList"
                          :key="index" @dragenter="dragenter($event, index, 'detail')"
                          @dragover="dragover($event, index)" @dragstart="dragstart(index)"
                          draggable="!disableDialogFormEidt">
                          <img class="w-full h-full" :src="photo.pictureUrl">
                          <div class="photoOverlay absolute top-0 left-0 flex items-center justify-center w-full h-full"
                            style="background-color: rgba(0, 0, 0, 0.5);">
                            <a-icon v-if="!disableDialogFormEidt" @click="photoDelete(index, 'detail')" class="cursor-pointer"
                              :style="{fontSize: '20px', color: 'white'}" type="delete" ></a-icon>
                            <a-icon v-if="disableDialogFormEidt" @click="catPhoto(photo.pictureUrl)" class="cursor-pointer"
                              :style="{fontSize: '25px', color: 'white'}" type="zoom-in" ></a-icon>
                          </div>
                        </div>
                        <label v-if="!disableDialogFormEidt" for="detailPhotoInput"
                          class="flex border items-center justify-center flex-col w-24 h-24">
                          <a-icon type="plus" :style="{fontSize: '40px'}"></a-icon>
                        </label>
                      </div>
                      <input id="detailPhotoInput" type="file" accept=“image/*” ref="detailPhotoInput"
                        style="display: none;" @change="photoInputChange('detail')" />
                    </a-form-model-item>
                  </a-col>
                </a-row>
                <a-row :gutter="24">
                  <a-col :span="1"></a-col>
                  <a-col :span="10">
                    <a-form-model-item label="商品排序 :">
                      <a-input type="number" :disabled="disableDialogFormEidt" v-model="dialogForm.categoryOrder" />
                    </a-form-model-item>
                  </a-col>
                  <a-col :span="2"></a-col>
                  <a-col :span="10">
                    <a-form-model-item label="是否生效 :">
                      <a-radio-group name="effectiveStatus" :default-value="dialogForm.effective"
                        v-model="dialogForm.effective" :disabled="disableDialogFormEidt">
                        <a-radio :value="0">
                          失效
                        </a-radio>
                        <a-radio :value="1">
                          生效
                        </a-radio>
                      </a-radio-group>
                    </a-form-model-item>
                  </a-col>
                </a-row>
                <a-row :gutter="24">
                  <a-col :span="1"></a-col>
                  <a-col :span="10">
                    <a-form-model-item label="列表页商品标签 :">
                      <a-select v-model="dialogForm.commodityTags" mode="tags" placeholder="请选择列表页商品标签"
                        :default-value="dialogForm.commodityTags" :disabled="disableDialogFormEidt"
                        @change="commodityTagsChange">
                        <a-select-option v-for="i in commodityTagMap" :key="i">
                          {{ i }}
                        </a-select-option>
                      </a-select>
                    </a-form-model-item>
                  </a-col>
                  <a-col :span="2"></a-col>
                  <a-col :span="10">
                    <a-form-model-item label="详情页商品标签 :">
                      <a-select v-model="dialogForm.detailTags" mode="tags" placeholder="请选择详情页商品标签"
                        :default-value="dialogForm.detailTags" :disabled="disableDialogFormEidt"
                        @change="detailTagsChange">
                        <a-select-option v-for="i in detailTagMap" :key="i">
                          {{ i }}
                        </a-select-option>
                      </a-select>
                    </a-form-model-item>
                  </a-col>
                </a-row>
                <a-row type="flex" justify="center">
                  <a-space v-if="!disableDialogFormEidt" size="large">
                    <a-button @click="dialogButtonClick(true)" size="large" type="primary">
                      配置
                    </a-button>
                    <a-button @click="dialogButtonClick(false)" size="large">
                      取消
                    </a-button>
                  </a-space>
                  <a-button v-else @click="dialogButtonClick(false)" size="large">
                    返回
                  </a-button>
                </a-row>
              </a-card>
            </a-form-model>
          </div>
        </div>
      </div>
    </div>
    <!-- /Page Body -->
  </div>
  <!-- /Page Content -->
  <div th:replace="/system/resource/base/baseFoot.template"></div>
  <script
    th:src="${application.resourceUrl}+'/assets/js/datatable/jquery.dataTables.min.js?'+${application.JSVERSION}"></script>
  <script
    th:src="${application.resourceUrl}+'/assets/js/datatable/dataTables.tableTools.min.js?'+${application.JSVERSION}"></script>
  <script
    th:src="${application.resourceUrl}+'/assets/js/datatable/dataTables.bootstrap.min.js?'+${application.JSVERSION}"></script>
  <script th:src="${application.resourceUrl}+'/bboss/js/datatable/DT_bootstrap.js?'+${application.JSVERSION}"></script>
  <script
    th:src="${application.resourceUrl}+'/assets/js/validation/bootstrapValidator.js?'+${application.JSVERSION}"></script>
  <script
    th:src="${application.resourceUrl}+'/assets/js/validation/bootstrapValidator_zh_CN.js?'+${application.JSVERSION}"></script>
  <script
    th:src="${application.resourceUrl}+'/bboss/js/validator/bootstrapValidator-extend.js?'+${application.JSVERSION}"></script>
  <script
    th:src="${application.resourceUrl}+'/bboss/js/datatable/datatable_client.js?'+${application.JSVERSION}"></script>
  <script
    th:src="${application.resourceUrl}+'/bboss/js/datatable/datatable_server.js?'+${application.JSVERSION}"></script>
  <script th:src="${application.resourceUrl}+'/bboss/js/form/searchForm.js?'+${application.JSVERSION}"></script>
  <script th:src="${application.resourceUrl}+'/assets/js/select2/select2.min.js?'+${application.JSVERSION}"></script>
  <script th:src="${application.resourceUrl}+'/bboss/js/select2/selectTab.js?'+${application.JSVERSION}"></script>
  <script th:src="${application.resourceUrl}+'/bboss/js/dialog/dialog-page.js?'+${application.JSVERSION}"></script>
  <script
    th:src="${application.resourceUrl}+'/bboss/js/dialog/bboss-dialog-page.js?'+${application.JSVERSION}"></script>
  <script
    th:src="${application.resourceUrl}+'/assets/js/jquery-file-upload/js/vendor/jquery.ui.widget.js?'+${application.JSVERSION}"></script>
  <script
    th:src="${application.resourceUrl}+'/assets/js/jquery-file-upload/js/jquery.iframe-transport.js?'+${application.JSVERSION}"></script>
  <script
    th:src="${application.resourceUrl}+'/assets/js/jquery-file-upload/js/jquery.fileupload.js?'+${application.JSVERSION}"></script>
  <script th:src="${application.resourceUrl}+'/assets/js/lightbox/js/lightbox.js?'+${application.JSVERSION}"></script>
  <script th:src="${application.resourceUrl}+'/bboss/js/upload/bboss-fileUpload.js?'+${application.JSVERSION}"></script>

  <script src="https://cdn.test.bestpay.net/orange/moment-with-locales.min.js"></script>
  <script src="https://cdn.test.bestpay.net/orange/vue.2.6.9.js"></script>
  <script src="https://cdn.test.bestpay.net/orange/antd.1.6.5.js"></script>
  <script src="https://cdn.test.bestpay.net/orange/axios.0.20.0.js"></script>
  <script src="https://cdn.test.bestpay.net/orange/antd-with-locales.1.6.5.js"></script>

  <!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment-with-locales.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.21.0/axios.min.js"></script>
  <script src="./antd.1.6.5.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.9/vue.min.js"></script>
  <script src="./antd-with-locales.1.6.5.js"></script> -->

  <!--Page Related Scripts-->
  <script th:inline="javascript">
    /**
 * 增强版：解决js计算丢失精度的问题
 */
    var floatObj = function () {
      /*
       * 判断obj是否为一个整数
       */
      function isInteger (obj) {
        return Math.floor(obj) === obj;
      }

      /*
       * 将一个浮点数转成整数，返回整数和倍数。如 3.14 >> 314，倍数是 100
       * @param floatNum {number} 小数
       * @return {object}
       *   {times:100, num: 314}
       */
      function toInteger (floatNum) {
        var ret = { times: 1, num: 0 };
        var isNegative = floatNum < 0;
        if (isInteger(floatNum)) {
          ret.num = floatNum;
          return ret;
        }
        var strfi = floatNum + '';
        var dotPos = strfi.indexOf('.');
        var len = strfi.substr(dotPos + 1).length;
        var times = Math.pow(10, len);
        var intNum = parseInt(Math.abs(floatNum) * times + 0.5, 10);
        ret.times = times;
        if (isNegative) {
          intNum = -intNum;
        }
        ret.num = intNum;
        return ret;
      }

      /*
       * 核心方法，实现加减乘除运算，确保不丢失精度
       * 思路：把小数放大为整数（乘），进行算术运算，再缩小为小数（除）
       *
       * @param a {number} 运算数1
       * @param b {number} 运算数2
       * @param digits {number} 精度，保留的小数点数，比如 2, 即保留为两位小数
       * @param op {string} 运算类型，有加减乘除（add/subtract/multiply/divide）
       *
       */
      function operation (a, b, digits, op) {
        var o1 = toInteger(a);
        var o2 = toInteger(b);
        var n1 = o1.num;
        var n2 = o2.num;
        var t1 = o1.times;
        var t2 = o2.times;
        var max = t1 > t2 ? t1 : t2;
        var result = null;
        switch (op) {
          case 'add':
            if (t1 === t2) { // 两个小数位数相同
              result = n1 + n2;
            } else if (t1 > t2) { // o1 小数位 大于 o2
              result = n1 + n2 * (t1 / t2);
            } else { // o1 小数位 小于 o2
              result = n1 * (t2 / t1) + n2;
            }
            return (result / max).toFixed(digits);
          case 'subtract':
            if (t1 === t2) {
              result = n1 - n2;
            } else if (t1 > t2) {
              result = n1 - n2 * (t1 / t2);
            } else {
              result = n1 * (t2 / t1) - n2;
            }
            return (result / max).toFixed(digits);
          case 'multiply':
            result = (n1 * n2) / (t1 * t2);
            return result.toFixed(digits);
          case 'divide':
            result = (n1 / n2) * (t2 / t1);
            return result.toFixed(digits);
        }
      }

      // 加减乘除的四个接口  加减乘除（add/subtract/multiply/divide）
      function add (a, b, digits) {
        return operation(a, b, digits, 'add');
      }
      function subtract (a, b, digits) {
        return operation(a, b, digits, 'subtract');
      }
      function multiply (a, b, digits) {
        return operation(a, b, digits, 'multiply');
      }
      function divide (a, b, digits) {
        return operation(a, b, digits, 'divide');
      }

      // exports
      return {
        add: add,
        subtract: subtract,
        multiply: multiply,
        divide: divide
      };
    }();
    function jsonSecurity (url) {
      url = url.replace(/\\/g, "@@"); //反斜杠转换为@@
      url = url.replace(/\$/g, "--"); //$符转换为--
      url = url.replace(/\|/g, "^^"); //竖杠转换为^^
      url = url.replace(/%/g, "!!");  //%转换为!!
      url = url.replace(/\"/g, "=="); //双引号转换为==
      url = url.replace(/\'/g, "**"); //单引号转换为**
      return url;
    };

    const http = axios.create({
      timeout: 5000, // 请求超时时间
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      transformRequest: [function (data) {
        let ret = ''
        for (let it in data) {
          if (typeof data[it] === 'string') {
            ret += encodeURIComponent(it) + '=' + jsonSecurity(data[it]) + '&'
          } else {
            ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&'
          }
        }
        return ret
      }],
    });

    http.interceptors.response.use(response => {
      return response.data;
    });

    function getBase64 (file) {
      return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = () => resolve(reader.result);
        reader.onerror = error => reject(error);
      });
    }

    /** 类目扁平数组，在 created() 获取类目 tree 数据进行扁平化后赋值 */
    let categorysFlatList = [];

    // 扁平数组
    function treeToList (tree = []) {
      let queen = [];
      const out = [];
      queen = queen.concat(JSON.parse(JSON.stringify(tree)));
      while (queen.length) {
        const first = queen.shift()
        if (first.children) {
          queen = queen.concat(first.children)
          delete first.children
        }
        out.push(first)
      }
      return out
    }

    /** 去除类目中的空children，避免页面多渲染层级 */
    function removechild (arr) {
      if (arr.children && arr.children.length === 0) {
        delete arr.children;
      }
      if (arr.children && arr.children.length) {
        arr.children.map(item => removechild(item));
      }
      return arr;
    }

    /** 渲染表格类目列，返回类目对应的名称 */
    const getRowCategoryName = (text) => {
      const categoryItem = categorysFlatList.find(category => category.categoryId === text);
      return categoryItem ? categoryItem.categoryName : '';
    };

    /** 渲染表格是否生效列，返回对应名称 */
    const effectiveNameMap = ['失效', '生效'];
    const getRowEffectiveName = (text) => {
      return effectiveNameMap[text];
    }

    const { locales } = window.antd;

    /** 表格数据列配置 */
    const tableColumns = [
      {
        title: 'id',
        dataIndex: 'id',
        align: 'center',
        width: 80,
      },
      {
        title: '商品主标题',
        dataIndex: 'commodityMainTitle',
        align: 'center',
        width: 150,
      },
      {
        title: '商品编码',
        dataIndex: 'spuId',
        align: 'center',
        width: 150,
      },
      {
        title: '品牌名称',
        dataIndex: 'brandName',
        align: 'center',
        width: 150,
      },
      {
        title: '一级类目',
        dataIndex: 'categoryIdOne',
        align: 'center',
        width: 150,
        customRender: getRowCategoryName,
      },
      {
        title: '二级类目',
        dataIndex: 'categoryIdTwo',
        width: 150,
        align: 'center',
        customRender: getRowCategoryName,
      },
      {
        title: '三级类目',
        dataIndex: 'categoryIdThree',
        align: 'center',
        width: 150,
        customRender: getRowCategoryName,
      },
      {
        title: '排序',
        dataIndex: 'categoryOrder',
        align: 'center',
        width: 80,
      },
      {
        title: '是否生效',
        dataIndex: 'effective',
        align: 'center',
        width: 100,
        customRender: getRowEffectiveName,
      },
      // {
      //   title: '配置位置',
      //   dataIndex: 'position',
      //   align: 'center',
      //   width: 100,
      // },
      {
        title: '最后修改时间',
        dataIndex: 'updatedAt',
        align: 'center',
        width: 100,
      },
      {
        title: '修改人',
        dataIndex: 'updatedBy',
        align: 'center',
        width: 100,
      },
      {
        title: '操作',
        align: 'center',
        dataIndex: 'action',
        fixed: 'right',
        width: 200,
        scopedSlots: { customRender: 'action' },
      }
    ]

    const EditableCell = {
      template: `
          <div class="editable-cell" :class="[onhandPriceError ?'border border-red-500': '']">
            <div v-if="editable" class="flex justify-center items-center">
              <a-input :type="inputType" :value="value" @change="handleChange" @pressEnter="check" />
              <a-icon type="check" class="ml-2" @click="check" />
            </div>
            <div v-else class="relative flex justify-center items-center px-8">
              {{ value }}
              <a-icon v-if="!disableEdit" type="edit" class="absolute right-1 top-1/4" @click="edit" />
            </div>
          </div>
        `,
      props: {
        text: String,
        disableEdit: Boolean,
        onhandPriceError: Boolean,
        inputType: String,
      },
      data () {
        return {
          value: this.text,
          editable: false,
        };
      },
      methods: {
        handleChange (e) {
          const value = e.target.value;
          this.value = value;
        },
        check () {
          this.editable = false;
          this.$emit('change', this.value);
        },
        edit () {
          this.editable = true;
        },
      },
    };
    moment.locale('zh-cn');
    var vm = new Vue({
      el: '#app',
      components: {
        EditableCell,
      },
      data: {
        /** 展示 table 页面 */
        showTablePage: true,
        // table 数据
        /** 搜索栏样式配置 */
        layout: {
          labelCol: { span: 7 },
          wrapperCol: { span: 17 },
        },
        /** 搜索栏数据 */
        searchForm: {},
        /** 品牌列表 */
        brandList: [],
        /** 类目 tree */
        categorys: [],
        /** 属性 list */
        attributeList: [],
        /** 是否生效选择项 */
        effectiveOptions: [
          {
            label: '是',
            value: 1,
          },
          {
            label: '否',
            value: 0,
          },
        ],
        queryTableLoading: false,
        /** 分页器 */
        pagination: {
          showSizeChanger: true,
          showQuickJumper: true,
          total: null,
          pageSize: 10,
          current: 1,
          showTotal: (total, range) => `共${total}条`,
          pageSizeOptions: ['10', '25', '50', '100'],
          buildOptionText: (size) => {
            return `${size.value}条/页`
          }
        },
        /** 表格分页数据查询中标识位 */
        loading: false,
        /** 表格数据 */
        tableData: [],

        // 弹窗数据
        /** 弹窗类型 0 新增 1 修改 2 详情 */
        dialogType: 0,
        dialogForm: {
          // 商品主标题
          commodityMainTitle: '',
          // 商品副标题
          commoditySubtitle: '',
          // 已选中类目
          categorys: [],
          // 品牌
          brandId: '',
          // 商品排序
          categoryOrder: null,
          // 是否生效，0不生效 1生效
          effective: null,
          // 是否虚拟商品 0不是 1是
          virtualCommodity: 0,
          // 充值账户类型 ("mobile", "手机号"), ("QQ", "QQ"),("wechat", "微信")
          rechargeAccountType: null,
          attributeRowList: [
            {
              attributeName: '',
              attributeId: '',
              attributeValueName: [],
              attributeValueId: [],
            },
          ],
          /** 是否自动定价 */
          autoSetPrice: 0,
          /** 百分比自动定价 */
          precentPrice: '',
          /** 数值自动定价 */
          amountPrice: '',
          // 属性 table 标题栏
          tableRowList: [],
          // 属性 table 行数据
          tableDataList: [],
          // 主图照片列表
          mainPhotoImgList: [],
          // 详情照片列表
          detailPhotoImgList: [],
          // 列表页商品标签
          commodityTags: [],
          // 详情页商品标签
          detailTags: [],
        },
        // 存储子属性的选择项，每一项的值都是
        attributeVlaueOptionsList: [],
        // 控制照片拖拽
        dragIndex: '',
        dragEnterIndex: '',
        // 列表页标签的枚举值
        commodityTagMap: [],
        // 详情页标签的枚举值
        detailTagMap: [],
        detailTags: [],
        commodityTags: [],
      },

      methods: {
        /** 浏览图片 */
        catPhoto(url){
          console.log("浏览图片" , url)
          // position: absolute;left: 50%;top: 50%;transform: translate(-50%, -50%);max-width: 85vw;max-height: 85vh;
          let imgDom = "<div style='width: 100vw;position: fixed;left: 0;top: 0;z-index: 9999;height: 100vh;background: rgba(0,0,0,0.6);' >"
          imgDom += "<img src='" + url + "' style='position: absolute;left: 50%;top: 50%;transform: translate(-50%, -50%);max-width: 85vw;max-height: 85vh;' ></img>"
          imgDom += "</div>"
          const PicDom = $(imgDom)
          $("body").append( PicDom )
          PicDom.click(function(){
            $(this).remove();
          });
          
        },
        /** 搜索栏类目过滤 */
        categorySearchFilter (inputValue, path) {
          return path.some(option => option.categoryName.toLowerCase().indexOf(inputValue.toLowerCase()) > -1);
        },
        /** 搜索栏类目选择赋值 */
        searchFromCategoryChange (value, selectedOptions) {
          this.searchForm.categorys = value;
        },
        /** 查询表格数据 */
        async queryTableData () {
          console.log('查询表格数据');
          if (!this.searchForm) {
            return;
          }
          // 组装表格查询参数
          const searchTableDataParams = {
            ...this.searchForm,
            effectiveInt: this.searchForm.effective,
            categoryIdOne: this.searchForm.categorys && this.searchForm.categorys[0],
            categoryIdTwo: this.searchForm.categorys && this.searchForm.categorys[1],
            categoryIdThree: this.searchForm.categorys && this.searchForm.categorys[2],
            size: this.pagination.pageSize,
            current: this.pagination.current,
          }
          for (let key in searchTableDataParams) {
            if (searchTableDataParams[key] === undefined) {
              delete searchTableDataParams[key]
            }
          }
          this.queryTableLoading = true;
          console.log('表格查询参数', searchTableDataParams);
          // 数据查询
          const url = '/PF/service/shoppingMallConfigurationService/commodityQuery.do';
          const { success, result, errorMsg } = await http.post(url, searchTableDataParams).finally(() => {
            this.queryTableLoading = false;
          });
          console.log(result, '查询表格数据');
          if (!success) {
            this.$message.error(errorMsg);
            return;
          }
          result.records.map(item => {
            item.effective = item.effectiveInt;
          });
          this.pagination.total = result.total,
            this.tableData = result.records;
        },
        /** 重置搜索查询条件 */
        resetSearchFormInfo () {
          this.searchForm = {};
          if (this.showTablePage) {
            this.$refs.searchFormCategoryCascader.value = [];
          }
          console.log('重置搜索查询条件');
        },
        /** 分页器事件处理 */
        handleTableChange (pagination) {
          // 设置分页器数据
          this.$set(this, 'pagination', pagination);
          // 查询 table 数据
          this.queryTableData();
        },
        /** 展示详情弹窗，用于 0 新增，1 修改，2 查看 */
        async showDetailDialog (type, record) {
          this.dialogType = type;
          if (type === 0) {
            // 重置 dialogForm 的值为空
            this.dialogForm = {
              commodityMainTitle: '',
              commoditySubtitle: '',
              categorys: [],
              brandId: '',
              categoryOrder: null,
              effective: 1,
              virtualCommodity: 0,
              rechargeAccountType: null,
              attributeRowList: [
                {
                  attributeName: '',
                  attributeId: '',
                  attributeValueName: [],
                  attributeValueId: [],
                },
              ],
              autoSetPrice: 0,
              precentPrice: null,
              amountPrice: null,
              attributeVlaueOptionsList: [],
              tableRowList: [],
              tableDataList: [],
              mainPhotoImgList: [],
              detailPhotoImgList: [],
              commodityTags: [],
              detailTags: [],
            }
          } else {
            // 通过接口查询已配置商品信息
            const url = '/PF/service/shoppingMallConfigurationService/commodityDetailsQuery.do';
            const params = {
              id: record.id,
              spuId: record.spuId,
            };
            console.log(params, '查询已配置商品信息参数');
            const { success, result, errorMsg } = await http.post(url, params);
            console.log(result, '查询已配置商品信息');
            if (!success) {
              this.$message.error(errorMsg);
              return;
            }
            dialogFormTemp = {
              id: result.id,
              spuId: result.spuId,
              commodityMainTitle: result.commodityMainTitle,
              commoditySubtitle: result.commoditySubtitle,
              rechargeAccountType: (result.virtualCommodity && result.rechargeAccountType) ? result.rechargeAccountType.split(',') : [],
              virtualCommodity: result.virtualCommodity,
              categorys: [result.categoryIdOne, result.categoryIdTwo, result.categoryIdThree],
              brandId: result.brandId,
              categoryOrder: result.categoryOrder,
              effective: result.effectiveInt,
              attributeRowList: [],
              attributeVlaueOptionsList: [],
              autoSetPrice: result.pricingType,
              precentPrice: result.pricingType === 1 ? result.pricingValue : null,
              amountPrice: result.pricingType === 2 ? floatObj.divide(Number(result.pricingValue)  , 100 , 2) : null,
              tableRowList: [],
              tableDataList: [],
              mainPhotoImgList: result.commodityPictureVos,
              detailPhotoImgList: result.commodityPictureDetailsVos,
              detailTags: result.detailTags ? JSON.parse(result.detailTags) : [],
              commodityTags: result.commodityTags ? JSON.parse(result.commodityTags) : [],
            };
            // 组装 this.dialogForm.attributeRowList 数据
            const firstAttrValueList = result.commoditySkuVos[0].commodityAttributeVos;
            for (let i = 0; i < firstAttrValueList.length; i++) {
              dialogFormTemp.attributeRowList.push({
                attributeName: firstAttrValueList[i].attributeName,
                attributeId: firstAttrValueList[i].attributeId,
                attributeValueName: [],
                attributeValueId: [],
              });
            }
            // 然后再遍历所有的行数，找出每种的属性值
            // 把table的数据也一块生成，不然还得第二次遍历
            for (let i = 0; i < result.commoditySkuVos.length; i++) {
              // 遍历每一行都先给table添加一行数据, commodityAttributeVos 数组用于存储列属性数据，方便提交时组装数据。
              dialogFormTemp.tableDataList.push({ commodityAttributeVos: [] });
              // 遍历每一列的数据。列数是固定的
              for (let j = 0; j < firstAttrValueList.length; j++) {
                const valueItem = result.commoditySkuVos[i].commodityAttributeVos[j];
                const skuId = result.commoditySkuVos[i].skuId
                // 填充每一行table数据的列
                dialogFormTemp.tableDataList[i][valueItem.attributeId] = valueItem.attributeValueName;
                // 将属性的相关内容
                dialogFormTemp.tableDataList[i].commodityAttributeVos.push({
                  attributeId: valueItem.attributeId,
                  attributeName: valueItem.attributeName,
                  attributeValueName: valueItem.attributeValueName,
                  attributeValueId: valueItem.attributeValueId,
                  skuId
                });
                // 将属性值添加到属性行的属性值数组中,这样全量添加有重复的数据要去重
                // 后端返回的数据乱序，不能直接使用循环的变量取值
                const index = dialogFormTemp.attributeRowList.findIndex((rowItem) => rowItem.attributeId === valueItem.attributeId);
                dialogFormTemp.attributeRowList[index].skuId = skuId
                dialogFormTemp.attributeRowList[index].attributeValueName.push(valueItem.attributeValueName);
                dialogFormTemp.attributeRowList[index].attributeValueId.push(valueItem.attributeValueId);
              }
              dialogFormTemp.tableDataList[i].skuId = result.commoditySkuVos[i].skuId;
              // dialogFormTemp.tableDataList[i].sellingPrice = result.commoditySkuVos[i].sellingPrice / 100;
              dialogFormTemp.tableDataList[i].sellingPrice = floatObj.divide(result.commoditySkuVos[i].sellingPrice , 100 , 2);
              
              if (result.pricingType === 0) {
                // dialogFormTemp.tableDataList[i].onHandPrice = result.commoditySkuVos[i].onHandPrice / 100;
                dialogFormTemp.tableDataList[i].onHandPrice = floatObj.divide(result.commoditySkuVos[i].onHandPrice , 100 , 2);
              } else {
                // dialogFormTemp.tableDataList[i].onHandPrice = result.pricingType === 1 ? `*${result.pricingValue}%` : `+${Number(result.pricingValue) / 100}`;
                dialogFormTemp.tableDataList[i].onHandPrice = result.pricingType === 1 ? `*${result.pricingValue}%` : `+${floatObj.divide(Number(result.pricingValue) , 100 , 2)}`;
              }
              dialogFormTemp.tableDataList[i].key = result.commoditySkuVos[i].skuId;
              dialogFormTemp.tableDataList[i].onhandPriceError = false;
            }
            // 将属性行中的属性值进行去重
            dialogFormTemp.attributeRowList.forEach(item => {
              item.attributeValueName = Array.from(new Set(item.attributeValueName));
              item.attributeValueId = Array.from(new Set(item.attributeValueId));
            });
            // 组装属性值下拉菜单列表
            dialogFormTemp.attributeRowList.forEach(row => {
              dialogFormTemp.attributeVlaueOptionsList.push(
                this.attributeList.find(
                  attrItem => attrItem.attributeId === row.attributeId
                ).attributeValuesVoList
              );
            });
            // 当修改的时候需要将已保存的选项置为disabled，不允许取消
            dialogFormTemp.attributeVlaueOptionsList.forEach(
              // options 是每个属性值的下拉菜单列表
              (options, optionsIndex) => {
                options.forEach(
                  // option 是每个下拉菜单中的单个选项
                  option => {
                    if (dialogFormTemp.attributeRowList[optionsIndex].attributeValueId.indexOf(option.attributeValueId) > -1) {
                      option.disabled = true;
                    }
                  }
                );
              }
            );
            this.dialogForm = dialogFormTemp;
            this.createdTableRowTitleList('init');
          }
          // 清空一下搜索条件，方便新增或修改后再次查询内容
          this.resetSearchFormInfo();
          this.showTablePage = false;
        },
        getBrandName (brandId) {
          const item = this.brandList.find(brand => brand.brandId === brandId);
          if (item) {
            return item.brandName;
          }
          return '';
        },
        /** 弹窗类目选择赋值 */
        dialogCategoryChange (value) {
          this.dialogForm.categorys = value;
        },
        /** 增删属性行 */
        attrbitueRowChange (rowIndex) {
          if (rowIndex === 0) {
            this.dialogForm.attributeRowList.push({
              attributeName: '',
              attributeId: '',
              attributeValueName: [],
              attributeValueId: [],
            });
            this.dialogForm.attributeVlaueOptionsList.push([]);
            return;
          }
          const list = [...this.dialogForm.attributeRowList];
          const listOptoins = [...this.dialogForm.attributeVlaueOptionsList];
          list.splice(rowIndex, 1);
          listOptoins.splice(rowIndex, 1);
          this.dialogForm.attributeRowList = list;
          this.dialogForm.attributeVlaueOptionsList = listOptoins;
          this.createdTableRowTitleList();
        },
        /** 属性选择器选择回调处理 */
        dialogAttributeSelect (value, rowIndex) {
          console.log(value)
          // 设置操作行的属性值
          this.dialogForm.attributeRowList[rowIndex].attributeId = value.key;
          this.dialogForm.attributeRowList[rowIndex].attributeName = value.label;
          // 重置属性值选择项
          this.$set(
            this.dialogForm.attributeVlaueOptionsList,
            rowIndex,
            this.attributeList.find(attrItem => attrItem.attributeId === value.key).attributeValuesVoList
          )
          // 重置已选中的属性值
          this.dialogForm.attributeRowList[rowIndex].attributeValueName = [];
          this.dialogForm.attributeRowList[rowIndex].attributeValueId = [];
          (
            this.$refs[`attributeValueSelect${rowIndex}`][0].$children &&
            this.$refs[`attributeValueSelect${rowIndex}`][0].$children[0]
          ) && (
              // 强行清空当前行的属性值已选择内容。这里清的是属性值选择框展示的内容
              this.$refs[`attributeValueSelect${rowIndex}`][0].$children[0].$data._value = []
            );
            console.log("this.dialogForm.attributeVlaueOptionsList",this.dialogForm.attributeVlaueOptionsList)
          // 重新生成表格数据
          this.createdTableRowTitleList();
        },
        /** 属性值选择器选择回调 */
        dialogAttributeValueSelect (value, rowIndex) {
          this.dialogForm.attributeRowList[rowIndex].attributeValueId.push(value);
          const subAttrItem = this.dialogForm.attributeVlaueOptionsList[rowIndex].find(subAttr => subAttr.attributeValueId === value);
          this.dialogForm.attributeRowList[rowIndex].attributeValueName.push(subAttrItem.attributeValueName)
          // 为这个属性增加属性table数据行
          const list = this.dialogForm.attributeRowList.filter(row => row.attributeId !== this.dialogForm.attributeRowList[rowIndex].attributeId);
          const attributeRowList = this.dialogForm.attributeRowList[rowIndex]
          const tableData = this.createTableData(
            list,
            {
              attributeId: this.dialogForm.attributeRowList[rowIndex].attributeId,
              attributeName: this.dialogForm.attributeRowList[rowIndex].attributeName,
              attributeValueId: subAttrItem.attributeValueId,
              attributeValueName: subAttrItem.attributeValueName,
            },
            (
              this.dialogForm.tableDataList[this.dialogForm.tableDataList.length - 1]
              && this.dialogForm.tableDataList[this.dialogForm.tableDataList.length - 1].key) || 0,
          );
          this.dialogForm.tableDataList = [...this.dialogForm.tableDataList, ...tableData];
        },
        /** 属性值选择器删除某个属性值的回调 */
        dialogAttributeValueDeselect (value, rowIndex) {
          const index = this.dialogForm.attributeRowList[rowIndex].attributeValueId.findIndex(attrValue => attrValue === value);
          this.dialogForm.attributeRowList[rowIndex].attributeValueId.splice(index, 1);
          const attributeValueName = this.dialogForm.attributeRowList[rowIndex].attributeValueName[index];
          this.dialogForm.attributeRowList[rowIndex].attributeValueName.splice(index, 1);
          // 删除属性后，删除属性table中所有包含这个属性值的行
          const key = this.dialogForm.attributeRowList[rowIndex].attributeId;
          const list = this.dialogForm.tableDataList.filter(rowData => {
            return rowData[key] !== attributeValueName;
          });
          this.dialogForm.tableDataList = list;
        },
        /** 定价类型值变更 */
        priceTypeChangeHandle (e) {
          this.dialogForm.autoSetPrice = e.target.value;
          this.dialogForm.precentPrice = null;
          this.dialogForm.amountPrice = null;
          if (!this.dialogForm.tableDataList.length) {
            // 表格数组没值，说明先改了自动定价，还没生成表格数据。
            return;
          }
          this.dialogForm.tableDataList.forEach(data => data.onHandPrice = '');
          // 因为要变更到手价的渲染类型,重新生成表格数据
          this.createdTableRowTitleList('priceTypeChange');
        },
        /** 虚拟商品变更 */
        virtualChangeHandle (e) {
          if (!e.target.value) {
            this.dialogForm.rechargeAccountType = null;
            return;
          };
        },
        /** 自动定价值变更 */
        autoPriceChangeHandle (e) {
          // 校验数字格式
          let value = e.target.value;
          const valueString = value.toString();
          const valueArr = valueString.split('.');
          if (valueArr[1] && valueArr[1].length > 2) {
            valueArr[1] = valueArr[1].substring(0, 2);
            this.$message.error('自动定价最多两位小数');
          }
          value = Number([valueArr[0], valueArr[1]].join('.'));
          if (this.dialogForm.autoSetPrice === 1) {
            if (value < 100) {
              return;
            }
          }
          this.dialogForm[this.dialogForm.autoSetPrice === 1 ? 'precentPrice' : 'amountPrice'] = value;
          if (!this.dialogForm.tableDataList.length) {
            return;
          }
          // 值变更后，重新渲染表格
          this.dialogForm.tableDataList.forEach(data => data.onHandPrice = this.dialogForm.autoSetPrice === 1 ? `*${value}%` : `+${value}`);
        },
        /** 创建属性表格的标题头 */
        createdTableRowTitleList (status) {
          console.log('this.dialogForm.attributeRowList' , this.dialogForm.attributeRowList)

          const rowList = this.dialogForm.attributeRowList.map(rowItem => {
            return {
              title: rowItem.attributeName,
              dataIndex: rowItem.attributeId,
              align: 'center',
              width: 150,
            }
          });
          rowList.unshift({
            title: "SKUID",
            dataIndex: "skuId",
            align: 'center',
            width: 150,
          })
          rowList.push({
            title: '售价',
            dataIndex: 'sellingPrice',
            align: 'center',
            width: 100,
            scopedSlots: { customRender: this.dialogType === 2 ? 'text' : 'sellingPrice' },
          });
          rowList.push({
            title: '到手价',
            dataIndex: 'onHandPrice',
            align: 'center',
            width: 100,
            scopedSlots: { customRender: (this.dialogType !== 2 && this.dialogForm.autoSetPrice === 0) ? 'onHandPrice' : 'text' },
          });
          if (this.dialogType === 0) {
            rowList.push({
              title: '操作',
              align: 'center',
              width: 100,
              scopedSlots: { customRender: 'action' },
            });
          }
          this.dialogForm.tableRowList = rowList;
          if (status === 'priceTypeChange') {
            // 如果是定价类型变更，到手价已经被重置了，这里只用重新生成表格头，数据不用重新组装
            return;
          }
          // 修改初始化的时候已经生成好表格数据了。因为表格可能被删除过某一行，不能用选中的属性正向生成表格数据
          if (status !== 'init') {
            this.dialogForm.tableDataList = this.createTableData(this.dialogForm.attributeRowList);
          }
        },
        /** 生成属性表格行数据 */
        createTableData (attrResult, attrMap, startId) {
          let id = startId || 0;
          if (!attrResult.length) {
            // 说明现在属性只有第一行
            const tabledata = [
              {
                [attrMap.attributeId]: attrMap.attributeValueName,
                sellingPrice: '',
                onHandPrice: '',
                onhandPriceError: false,
                key: ++id,
                // 这时候生成的数据只有一列，所以这个列数组就一个值
                commodityAttributeVos: [
                  {
                    attributeId: attrMap.attributeId,
                    attributeName: attrMap.attributeName,
                    attributeValueName: attrMap.attributeValueName,
                    attributeValueId: attrMap.attributeValueId,
                  },
                ],
              }
            ];
            if (this.dialogForm.autoSetPrice === 0) {
              return tabledata;
            }
            tabledata[0].onHandPrice = this.dialogForm.autoSetPrice === 1 ? `*${this.dialogForm.precentPrice}%` : `+${this.dialogForm.amountPrice}`;
            return tabledata;
          }
          // 真实的 table 行数据
          let table = [];
          // 先生成第一个属性的数据行
          for (let i = 0; i < attrResult[0].attributeValueId.length; i++) {
            table.push({
              [attrResult[0].attributeId]: attrResult[0].attributeValueName[i],
              sellingPrice: '',
              onHandPrice: '',
              // 这时候生成的数据只有一列，所以这个列数组就一个值
              commodityAttributeVos: [
                {
                  attributeId: attrResult[0].attributeId,
                  attributeName: attrResult[0].attributeName,
                  attributeValueName: attrResult[0].attributeValueName[i],
                  attributeValueId: attrResult[0].attributeValueId[i],
                }
              ]
            });
          }
          // 把每一种属性都做一次遍历
          for (let i = 1; i < attrResult.length; i++) { // 总循环次数   size
            let tempTable = [];
            // 每一个属性的 每一个属性值做遍历  即表格的列数
            for (let j = 0; j < attrResult[i].attributeValueId.length; j++) {  // 大小
              // 把新的列数据和已有的列数据合并
              for (let k = 0; k < table.length; k++) { // 第一行 第二行
                tempTable.push({
                  ...table[k],
                  [attrResult[i].attributeId]: attrResult[i].attributeValueName[j],
                });
                // 新建一个数组，不然这个commodityAttributeVos会有引用导致内容重复
                tempTable[tempTable.length - 1].commodityAttributeVos = [...tempTable[tempTable.length - 1].commodityAttributeVos];
                // 为列数据增加属性数据
                tempTable[tempTable.length - 1].commodityAttributeVos.push({
                  attributeId: attrResult[i].attributeId,
                  attributeName: attrResult[i].attributeName,
                  attributeValueName: attrResult[i].attributeValueName[j],
                  attributeValueId: attrResult[i].attributeValueId[j],
                });
              }
            }
            // 每一轮大循环结束
            table = tempTable;
          }
          table = table.map(item => {
            const obj = {
              ...item,
              onhandPriceError: false,
              key: ++id,
            }
            if (attrMap) {
              // 这个地方都是新增属性值的，直接将行标记为可删除
              item.commodityAttributeVos.push(attrMap);
              return {
                ...obj,
                [attrMap.attributeId]: attrMap.attributeValueName,
              }
            }
            return obj;
          });
          if (this.dialogForm.autoSetPrice === 0) {
            return table;
          }
          table.forEach(data => {
            if (this.dialogForm.autoSetPrice === 1) {
              data.onHandPrice = this.dialogForm.precentPrice ? `*${this.dialogForm.precentPrice}%` : '';
            } else {
              data.onHandPrice = this.dialogForm.amountPrice ? `+${this.dialogForm.amountPrice}` : '';
            }
          });
          return table;
        },
        /** 属性表格行可编辑数据变更处理 */
        onCellChange (index, key, value) {
          const tableItem = this.dialogForm.tableDataList[index];
          tableItem[key] = value;
          if (key === 'onHandPrice') {
            if (Number(tableItem.onHandPrice) > Number(tableItem.sellingPrice)) {
              tableItem.onhandPriceError = true;
              this.$message.error('到手价不能大于售价');
            } else {
              tableItem.onhandPriceError = false;
            }
          }
        },
        /** 删除属性表格行数据 */
        deleteDialogAttrTableRow (index) {
          const tableList = [...this.dialogForm.tableDataList];
          this.dialogForm.tableDataList = tableList.filter((item, tableindex) => tableindex !== index);
        },
        /** 上传照片处理 */
        photoInputChange (type) {
          const reader = new FileReader();
          const file = this.$refs[`${type}PhotoInput`].files[0];
          if (!file) {
            return;
          }

          reader.readAsDataURL(file);
          reader.onload = async (e) => {
            const url = '/PF/service/fastDfsServer/upload.upload';
            const form = new FormData();
            form.append('file', file);
            form.append('attachPath1', file.name.split('.')[1]);

            // 调用图片上传接口
            const res = await axios.post(url, form).finally(() => {
              this.$refs[`${type}PhotoInput`].value = '';
            });
            const { success, result, errorMsg } = JSON.parse(res.data);
            console.log(result, '图片上传接口');
            if (!success) {
              this.$message.error(errorMsg);
              return;
            }
            this.dialogForm[`${type}PhotoImgList`].push({
              pictureUrl: result.fileUrl,
              fileGroup: result.fileGroup,
              fileName: result.fileName,
            });
          }
        },
        /** 删除照片 */
        async photoDelete (index, type) {
          const name = `${type}PhotoImgList`;
          const url = '/PF/service/fastDfsServer/delete.do';
          const params = {
            fileGroup: this.dialogForm[name][index].fileGroup,
            fileName: this.dialogForm[name][index].fileName,
          };
          // 调用图片删除接口
          console.log(params, '删除图片参数');
          const { success, result, errorMsg } = await http.post(url, params);
          console.log(result, '图片删除接口');
          if (!success) {
            this.$message.error(errorMsg);
            return;
          }
          if (result) {
            this.dialogForm[name].splice(index, 1);
          }
        },
        /** 照片拖拽排序 */
        dragstart (index) {
          this.dragIndex = index;
        },
        dragenter (e, index, type) {
          e.preventDefault();
          // 避免源对象触发自身的dragenter事件
          if (this.dragIndex !== index) {
            const list = this.dialogForm[`${type}PhotoImgList`];
            const source = list[this.dragIndex];
            list.splice(this.dragIndex, 1);
            list.splice(index, 0, source);
            // 排序变化后目标对象的索引变成源对象的索引
            this.dragIndex = index;
          }
        },
        dragover (e) {
          e.preventDefault();
        },
        /** 配置窗口按钮点击 */
        async dialogButtonClick (flag) {
          // 取消按钮直接重新展示table
          if (!flag) {
            this.showTablePage = true;
            setTimeout(() => {
              window.scrollTo(0, 0);
            }, 400);
            return;
          }
          if (this.dialogForm.commodityTags.length > 7) {
            return this.$message.error('列表页商品标签最多可选7个');
          }
          if (this.dialogForm.detailTags.length > 7) {
            return this.$message.error('详情页商品标签最多可选7个');
          }
          // 进行提交，this.dialogType === 0 新增，1 修改
          const url = `/PF/service/shoppingMallConfigurationFacade/${this.dialogType === 0 ? 'commodityAdd.do' : 'commodityChange.do'}`;
          const params = {
            commodityMainTitle: this.dialogForm.commodityMainTitle,
            commoditySubtitle: this.dialogForm.commoditySubtitle,
            categoryIdOne: Number(this.dialogForm.categorys[0]),
            categoryIdTwo: Number(this.dialogForm.categorys[1]),
            categoryIdThree: Number(this.dialogForm.categorys[2]),
            brandId: BigInt(this.dialogForm.brandId),
            categoryOrder: Number(this.dialogForm.categoryOrder),
            effectiveInt: this.dialogForm.effective,
            virtualCommodity: this.dialogForm.virtualCommodity,
            rechargeAccountType: this.dialogForm.rechargeAccountType ? this.dialogForm.rechargeAccountType.join() : '',
            pricingType: this.dialogForm.autoSetPrice,
            // pricingValue: (this.dialogForm.autoSetPrice === 0 ? '' : this.dialogForm.autoSetPrice === 1 ? this.dialogForm.precentPrice : Number(this.dialogForm.amountPrice) * 100).toString(),
            pricingValue: (this.dialogForm.autoSetPrice === 0 ? '' : this.dialogForm.autoSetPrice === 1 ? this.dialogForm.precentPrice : floatObj.multiply(Number(this.dialogForm.amountPrice) , 100 , 0)).toString(),
            commodityPictureVos: this.dialogForm.mainPhotoImgList,
            commodityPictureDetailsVos: this.dialogForm.detailPhotoImgList,
            commodityTags: this.dialogForm.commodityTags.toString(),
            detailTags: this.dialogForm.detailTags.toString(),
          }
          if (this.dialogType === 1) {
            params.id = this.dialogForm.id;
            params.spuId = this.dialogForm.spuId;
          }
          if (this.autoSetPrice === 1) {
            if (!this.dialogForm.precentPrice || Number(this.dialogForm.precentPrice) < 100) {
              return this.$message.error('请正确填写自动定价比例');
            }
          }
          if (params.virtualCommodity === 1) {
            if (!params.rechargeAccountType) {
              return this.$message.error('虚拟商品至少选择一个虚拟账号(QQ, 微信号，手机)');
            }
          }

          if (this.autoSetPrice === 2) {
            if (!this.dialogForm.amountPrice) {
              return this.$message.error('请正确填写自动定价金额');
            }
          }
          const errorRowIndex = this.dialogForm.tableDataList.findIndex((data) => !data.sellingPrice || (this.dialogForm.autoSetPrice === 0 && !data.onHandPrice));
          if (errorRowIndex >= 0) {
            return this.$message.error(`售价和到手价不能为空，请检查第${errorRowIndex + 1}行数据`);
          }
          params.commoditySkuVos = this.dialogForm.tableDataList.map(dataItem => {
            console.log("dataItem" , dataItem)
            return {
              skuId: dataItem.skuId || '',
              // sellingPrice: Number(dataItem.sellingPrice) * 100,
              sellingPrice: floatObj.multiply(Number(dataItem.sellingPrice) , 100 , 0),
              // onHandPrice: this.dialogForm.autoSetPrice === 0 ? Number(dataItem.onHandPrice) * 100 : null,
              onHandPrice: this.dialogForm.autoSetPrice === 0 ? floatObj.multiply(Number(dataItem.onHandPrice) , 100 , 0) : null,
              commodityAttributeVos: dataItem.commodityAttributeVos,
            }
          });
          const errorRow = params.commoditySkuVos.find(item => Number(item.onHandPrice) > Number(item.sellingPrice));
          if (errorRow) {
            this.$message.error(`存在错误行到手价大于售价, 属性值为：${params.commoditySkuVos.commodityAttributeVos.map(item => item.attributeValueName).join('-')}`);
            return;
          }
          // 调用接口新增或修改
          console.log(params, '新增或修改参数');
          for (let key in params) {
            if (typeof params[key] === 'object') {
              params[key] = JSON.stringify(params[key]);
            }
          }
          const { success, result, errorMsg } = await http.post(url, params);
          console.log(result, '新增或修改')
          if (!success) {
            this.$message.error(errorMsg);
            return;
          }
          // 更新 table 数据
          await this.queryTableData();
          this.showTablePage = true;
          setTimeout(() => {
            window.scrollTo(0, 0);
          }, 400);
        },
        commodityTagsChange (val) {
          this.dialogForm.commodityTags = val;
        },
        detailTagsChange (val) {
          this.dialogForm.detailTags = val;
        }
      },
      computed: {
        getDialogActionTitle () {
          return ['商品配置', '修改商品详情', '商品配置-详情'][this.dialogType]
        },
        disableDialogFormEidt () {
          return this.dialogType === 2;
        }
      },
      watch: {
      },
      async created () {
        this.queryTableData();
        // 查询类目列表
        const categoryUrl = '/PF/service/shoppingMallConfigurationService/commodityCategoryTreeQuery.do';
        const { success: categorySuccess, result: categoryResult, errorMsg: categoryErrorMsg } = await http.post(categoryUrl, {});
        console.log(categoryResult, '查询类目列表')
        if (!categorySuccess) {
          this.$message.error(categoryErrorMsg);
          return;
        }
        this.categorys = categoryResult.commodityCategoryVoList ? categoryResult.commodityCategoryVoList.map(item => removechild(item)) : [];
        // 扁平化类目数据，方便表格类目名称渲染
        categorysFlatList = treeToList(categoryResult.commodityCategoryVoList);
        // 查询品牌列表
        const brandUrl = '/PF/service/shoppingMallConfigurationService/brandQuery.do'
        const { success: brandSuccess, result: brandResult, errorMsg: brandErrorMsg } = await http.post(brandUrl, {});
        console.log(brandResult, '查询品牌列表');
        if (!brandSuccess) {
          this.$message.error(brandErrorMsg);
          return;
        }
        this.brandList = brandResult.brandQueryResVoList;
        // 查询属性列表配置
        const attributeUrl = '/PF/service/shoppingMallConfigurationService/commodityAttributeQuery.do'
        const { success: attributeSuccess, result: attributeResult, errorMsg: attributeErrorMsg } = await http.post(attributeUrl, {});
        console.log(attributeResult, '查询属性列表');
        if (!attributeSuccess) {
          this.$message.error(attributeErrorMsg);
          return;
        }
        this.attributeList = attributeResult.queryResVoList;
        // 查询列表页标签配置
        await http.get('/PF/service/excellentBusinessTagFacade/queryList.do?tagType=COMMODITY_TAGS&iDisplayStart=0&iDisplayLength=100').then((res) => {
          if (!res.success) {
            this.$message.error(res.errorMsg || '获取列表页商品标签列表失败');
            return;
          }
          this.commodityTagMap = res.result.list.map(item => item.value);
        });
        // 查询详情页标签配置
        await http.get('/PF/service/excellentBusinessTagFacade/queryList.do?tagType=DETAIL_TAGS&iDisplayStart=0&iDisplayLength=100').then((res) => {
          if (!res.success) {
            this.$message.error(res.errorMsg || '获取详情页商品标签列表失败');
            return;
          }
          this.detailTagMap = res.result.list.map(item => item.value);
        });
        console.log(this.commodityTagMap, this.detailTagMap);
      },
    });
  </script>
</body>
<!--  /Body -->

</html>